﻿using System;
using System.ServiceModel;
using System.Threading;
using Ninject.Core;
using Odin.Contracts.Data;
using Odin.Contracts.Services;
using Odin.Execution.Modules;
using IRemoteSessionManager = Odin.Execution.RemoteSessionManager.IRemoteSessionManager;


namespace Odin.Execution
{
	public class Core
	{
		public const string TestPage = "SilverlightTestPage.aspx";
		public static Core Instance = Kernel.Get<Core>();

		private Session _currentSession;

		private static IKernel _kernel;
		public static IKernel	Kernel
		{
			get
			{
				if( null == _kernel )
				{
					_kernel = new StandardKernel(new ServiceModule());
				}
				return _kernel;
			}
			set
			{
				_kernel = value;
			}
		}


		public Core()
		{
			
		}
		
		
		[Inject]
		public IWebServer WebServer { get; set; }

		[Inject]
		public ISessionManager LocalSessionManager { get; set; }

		[Inject]
		public IRemoteSessionManager RemoteSessionManager { get; set; }

		public Session	CreateSession(string xapPath, string startupObject)
		{
			var session = Kernel.Get<Session>();
			session.Identifier = Guid.NewGuid().ToString();
			session.XapPath = xapPath;
			session.StartupObject = startupObject;
			return session;
		}

		public void RunSession(Session session)
		{
			_currentSession = session;
			WebServer.EnsureHostIsRunning();
			ConfigureRemoteServices();
			WebServer.ClearDirectory();
			WebServer.PrepareDirectory(session);
			WebServer.PrepareRunner(session);
			RemoteSessionManager.BeginSession(session);
			LocalSessionManager.BeginSession(session);
		}

		public void ConfigureRemoteServices()
		{
			var remoteSessionManager = Kernel.Get<IRemoteSessionManager>();
			ServiceModule.SetAddressForService(remoteSessionManager as ICommunicationObject, WebServer.BaseUrl);
		}

		private readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
		public void WaitForCompletion(Session session)
		{
			var lastCheck = DateTime.Now;

			var workingSession = session;

			var thread = new Thread(
				() =>
					{
						for (; ; )
						{
							lock (workingSession)
							{
								var nextCheck = DateTime.Now;
								var methods = RemoteSessionManager.GetMethodsChangedSince(session, lastCheck);
								if (methods.Length >= 1)
								{
									lastCheck = nextCheck;

									foreach (var method in methods)
									{
										session.OnMethodChanged(method);
									}
								}
								workingSession = RemoteSessionManager.UpdateSession(workingSession);

								if (workingSession.Status == SessionStatus.Completed ||
								    workingSession.Status == SessionStatus.NoSession)
								{
									Thread.CurrentThread.Abort();
								}
							}
							Thread.Sleep(100);
						}
					}
				);
			thread.Start();

			for (; ;  )
			{
				if (workingSession.Status == SessionStatus.Completed ||
					workingSession.Status == SessionStatus.NoSession)
				{
					break;
				}
				Thread.Sleep(20);
			}

				
		}

		public void EndSession(Session session)
		{
			LocalSessionManager.EndSession(session);
			RemoteSessionManager.EndSession(session);
		}

		public void ShutDown()
		{
			WebServer.ShutDown();
		}
	}
}
